/*!
  @file libpng_helper.h
  @brief Brief Description
  @author Kyohei Otsu <kyon@ac.jaxa.jp>
  @date April, 2013
*/

#ifndef _LIBPNG_HELPER_H_
#define _LIBPNG_HELPER_H_

#include <png.h>
#include <stdio.h>

#include <string>
#include <tr1/memory> // for std::tr1::shared_ptr

namespace png
{

enum ColorMode {
  PNG_COLOR_RGB = PNG_COLOR_TYPE_RGB,
  PNG_COLOR_GRAY = PNG_COLOR_TYPE_GRAY,
};

//! class description 
/*! This is a detailed description of the class */
class PNG {
 public:

  typedef std::tr1::shared_ptr<PNG> Ptr;


  //! Constructor
  PNG() : memory_alloced_(false), width_(-1), height_(-1), channels_(-1), data_(new png_bytep) { }
  PNG(png_bytep *data, int width, int height, int channels) : width_(width), height_(height), channels_(channels) {
    // explicit copy
    allocMemory(width_, height_, channels_);
    for(int y = 0; y < height_; y++)
      for(int x = 0; x < width_*channels_; x++)
        data_[y][x] = data[y][x];
  }

  //! Destructor
  ~PNG() { releaseMemory(); }

  //! read png file from storage
  bool readFromStorage(const std::string& filename, const png_byte color_mode=PNG_COLOR_RGB);
  //! write png file to storage
  bool writeToStorage(const std::string& filename, const png_byte color_mode=PNG_COLOR_RGB);

  //! send png file via networks
  bool send(FILE *fp);
  //! receive png file via networks
  bool recv(FILE *fp);

  int width() const { return width_; }
  int height() const { return width_; }

 private:

  //! obtain array from file descriptor
  bool decode(FILE *fp, png_bytep *data);

  //! write array to file descriptor
  bool encode(png_bytep *data, FILE *fp);

  //! color conversion
  bool convertRGB2GRAY();
  //! color conversion
  bool convertGRAY2RGB();

  //! memory management
  int allocMemory(int width, int height, int channels);
  void releaseMemory();


  //! true if memory is alloced
  bool memory_alloced_;

  int width_;  //!< image width
  int height_; //!< image height
  int channels_; //!< image channels (1 or 3 ?)

  png_byte color_type_;
  png_byte bit_depth_;

  png_structp png_ptr_; //!< pointer to data
  png_infop info_ptr_;  //!< pointer to meta infomation 

  png_bytep *data_; //!< row image data (aka uchar**)

};

} // end of namespace

#endif
